home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ccdl151s.zip / SOURCE / REG386.C < prev    next >
C/C++ Source or Header  |  1997-03-15  |  5KB  |  206 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. #include        <stdio.h>
  23. #include        "expr.h"
  24. #include        "c.h"
  25. #include        "gen386.h"
  26.  
  27. /*
  28.  *      this module handles the allocation and de-allocation of
  29.  *      temporary registers. when a temporary register is allocated
  30.  *      the stack depth is saved in the field deep of the address
  31.  *      mode structure. when validate is called on an address mode
  32.  *      structure the stack is popped until the register is restored
  33.  *      to it's pre-push value.
  34.  */
  35. extern int cf_freedata,cf_freeaddress,cf_freefloat;
  36.  
  37.     AMODE push[1],pop[1];
  38. int             next_data,        /* Next available */
  39.                 next_addr;
  40. int             max_data,            /* Max available */
  41.                 max_addr;
  42. int                            next_float, max_float;
  43. long stackdepth,framedepth;
  44. int regs[3];
  45.  
  46. char regstack[20],rsold[30],rsdepth = 0,rsodepth=0;
  47.  
  48. void regini(void)
  49. {
  50.     rsdepth = rsodepth = 0;
  51. }
  52. void gen_push(int reg, int rmode, int flag)
  53. /*
  54.  *      this routine generates code to push a register onto the stack
  55.  */
  56. {       AMODE    *ap1;
  57.         ap1 = xalloc(sizeof(AMODE));
  58.         ap1->preg = reg;
  59.         ap1->mode = rmode;
  60.                 if (rmode == am_freg) {
  61.             FLOAT;
  62.                 }
  63.                 else {
  64.           gen_code(op_push,4,ap1,0);
  65.                     if (flag)
  66.                         framedepth+=4;
  67.                     else
  68.                         stackdepth +=4;
  69.                 }
  70. }
  71.  
  72. void gen_pop(int reg, int rmode, int flag)
  73. /*
  74.  *      generate code to pop the primary register in ap from the
  75.  *      stack.
  76.  */
  77. {       AMODE    *ap1;
  78.         ap1 = xalloc(sizeof(AMODE));
  79.         ap1->preg = reg;
  80.         ap1->mode = rmode;
  81.                 if (rmode == am_freg) {
  82.             FLOAT;
  83.                 }
  84.                 else {
  85.             gen_code(op_pop,4,ap1,0);
  86.                     stackdepth -=4;
  87.                 }
  88. }
  89. void pushregs(unsigned mask)
  90. {
  91.     int i;
  92.     int umask = 0x08000;
  93.     for (i=0; i < 4; i++) {
  94.         if (umask & mask)
  95.             gen_push(i,am_dreg,1);
  96.         umask >>=1;
  97.     }
  98.     umask = 0x080;
  99.     for (i=4; i < 8; i++) {
  100.         if (umask & mask)
  101.             gen_push(i,am_dreg,1);
  102.         umask >>=1;
  103.     }
  104. }
  105. /* This is ONLY called from the return.  Calling from any other place
  106.  * will leave the stack depth unpredictable... */
  107. void popregs(unsigned mask)
  108. {
  109.     int i;
  110.     int umask = 0x800;
  111.     for (i=7; i >= 4; i--) {
  112.         if (umask & mask) {
  113.             gen_pop(i,am_dreg,1);
  114.             stackdepth+=4;
  115.         }
  116.         umask >>=1;
  117.     }
  118.     umask = 0x8;
  119.     for (i=3; i >= 0; i--) {
  120.         if (umask & mask) {
  121.             gen_pop(i,am_dreg,1);
  122.             stackdepth+=4;
  123.         }
  124.         umask >>=1;
  125.     }
  126. }
  127. void initstack(void)
  128. /*
  129.  *      this routine should be called before each expression is
  130.  *      evaluated to make sure the stack is balanced and all of
  131.  *      the registers are marked free.
  132.  */
  133. {
  134.             rsdepth = rsodepth = 0;
  135.        next_data = 0;
  136.         next_addr = 0;
  137.         max_data = cf_freedata-1;
  138.         max_addr = cf_freeaddress-1;
  139.             next_float = 0;
  140.             max_float = cf_freefloat-1;
  141.             regs[0]=regs[1]=regs[2]=0;
  142. }
  143.  
  144. void mark(void)
  145. {
  146.     rsold[rsodepth++] = rsdepth;
  147. }
  148. void release(void)
  149. {
  150.     if (!rsodepth)
  151.         return;
  152.     rsodepth--;
  153.     while (rsdepth > rsold[rsodepth]) {
  154.         int data = regstack[--rsdepth];
  155.       gen_pop(data,am_dreg,0);
  156.     }
  157. }
  158. AMODE    *temp_data(void)
  159. /*
  160.  *      allocate a temporary data register and return it's
  161.  *      addressing mode.
  162.  */
  163. {       AMODE    *ap;
  164.         ap = xalloc(sizeof(AMODE));
  165.         ap->mode = am_dreg;
  166.         ap->preg = next_data % cf_freedata;
  167.         if( next_data > max_data )
  168.                 {
  169.                 gen_push(ap->preg,am_dreg,0);
  170.                                 regstack[rsdepth++] = ap->preg;
  171.                                 regs[ap->preg]--;
  172.                 max_data = next_data;
  173.                 }
  174.                 regs[ap->preg]++;
  175.         ++next_data;
  176.         return ap;
  177. }
  178.  
  179. void freedata(int dreg)
  180. {
  181.     if (dreg < cf_freedata && next_data > 0) {
  182.         --next_data;
  183.         regs[dreg]--;
  184.     }
  185. }
  186. void freeaddr(int areg)
  187. {
  188.     if (areg < cf_freeaddress && next_addr > 0) 
  189.         --next_addr;
  190. }
  191.         
  192. void freeop(AMODE *ap)
  193. /*
  194.  *      release any temporary registers used in an addressing mode.
  195.  */
  196. {       if( ap->mode == am_immed || ap->mode == am_direct )
  197.                 return;         /* no registers used */
  198.         if( ap->mode == am_dreg)
  199.                     freedata(ap->preg);
  200.                  else if (ap->mode == am_indisp)        
  201.                     freedata(ap->preg);
  202.                  else if (ap->mode == am_indispscale) {
  203.                     freedata(ap->preg);
  204.                     freedata(ap->sreg);
  205.                 }
  206. }